home *** CD-ROM | disk | FTP | other *** search
/ SGI Developer Toolbox 6.1 / SGI Developer Toolbox 6.1 - Disc 4.iso / src / demos / GL / flight / udpbrdcst.c < prev    next >
C/C++ Source or Header  |  1994-08-01  |  6KB  |  253 lines

  1. /*
  2.  * Copyright 1984-1991, 1992, 1993, 1994, Silicon Graphics, Inc.
  3.  * All Rights Reserved.
  4.  *
  5.  * This is UNPUBLISHED PROPRIETARY SOURCE CODE of Silicon Graphics, Inc.;
  6.  * the contents of this file may not be disclosed to third parties, copied or
  7.  * duplicated in any form, in whole or in part, without the prior written
  8.  * permission of Silicon Graphics, Inc.
  9.  *
  10.  * RESTRICTED RIGHTS LEGEND:
  11.  * Use, duplication or disclosure by the Government is subject to restrictions
  12.  * as set forth in subdivision (c)(1)(ii) of the Rights in Technical Data
  13.  * and Computer Software clause at DFARS 252.227-7013, and/or in similar or
  14.  * successor clauses in the FAR, DOD or NASA FAR Supplement. Unpublished -
  15.  * rights reserved under the Copyright Laws of the United States.
  16.  */
  17.  
  18. /*
  19.  *  udpbrdcst.c $Revision: 1.7 $
  20.  */
  21.  
  22. #include <stdio.h>
  23. #include <sys/time.h>
  24. #include "udpbrdcst.h"
  25.  
  26. #define DOG_MCAST_ADDR    "224.0.1.2"    /* official address */
  27. #define DEFAULT_TTL    8        /* packet time-to-live */
  28. #define MAX_TTL        32        /* can't go beyond the "site" */
  29. char multicast = 1;        /* if 1 use multicast instead of broadcast */
  30. char mcast_ttl = DEFAULT_TTL;    /* must be type "char" */
  31. char *mcast_ifaddr = NULL;    /* interface address to send to/recv from */
  32.  
  33. static struct sockaddr_in  hostaddr;
  34.  
  35.  
  36. /*
  37.  * Get a broadcast or multicast socket for the given service.  
  38.  * Return in "addr" the address to use in a "sendto" so that a message 
  39.  * can be sent.  The socket returned can be used to send a message, as well
  40.  * as receive a message.  Some interfaces will receive what
  41.  * they send, so be prepared to drop messages from yourself.
  42.  */
  43.  
  44. int
  45. getbroadcast(service, addr)
  46.     char *service;
  47.     struct sockaddr_in *addr;
  48. {
  49.     struct servent *sp;
  50.     int fd;
  51.     int on = 1;
  52.  
  53.     /* Get our port number */
  54.     sp = getservbyname(service, "udp");
  55.     if (sp == 0)
  56.     {
  57.     printf("Can't find udp service \"%s\"\n", service);
  58.     return(-2);
  59.     }
  60.  
  61.     /* Open the socket */
  62.     fd = socket(AF_INET, SOCK_DGRAM, 0);
  63.     if (fd < 0)
  64.     {
  65.     perror("socket");
  66.     return(-1);
  67.     }
  68.  
  69.     bzero(addr, sizeof(*addr));
  70.     addr->sin_addr.s_addr = INADDR_ANY;
  71.     addr->sin_family = AF_INET;
  72.     addr->sin_port = sp->s_port;
  73.     if (bind(fd, addr, sizeof(*addr)) < 0)
  74.     {
  75.     perror("bind");
  76.     close(fd);
  77.     return(-1);
  78.     }
  79.  
  80.     if (multicast)
  81.     {
  82.     struct ip_mreq mreq;
  83.     struct in_addr ifaddr;
  84.     char mcloop = 0;        /* must be type "char" */
  85.  
  86.     /* Disable loopback of mcast packets */
  87.     if (setsockopt(fd, IPPROTO_IP, IP_MULTICAST_LOOP, &mcloop, 
  88.         sizeof(mcloop)) < 0){
  89.         perror("setsockopt mcast loop");
  90.         close(fd);
  91.         return(-1);
  92.     }
  93.  
  94.     if (mcast_ttl < 0 || mcast_ttl > MAX_TTL)
  95.     {
  96.         mcast_ttl = DEFAULT_TTL;
  97.     }
  98.     if (setsockopt(fd, IPPROTO_IP, IP_MULTICAST_TTL, &mcast_ttl, 
  99.                sizeof(mcast_ttl)) < 0)
  100.     {
  101.         perror("setsockopt mcast ttl");
  102.         close(fd);
  103.         return(-1);
  104.     }
  105.  
  106.     /* Change the default interface (only useful on gateways) */
  107.     if (mcast_ifaddr != NULL)
  108.     {
  109.         struct hostent *hp;
  110.  
  111.         ifaddr.s_addr = inet_addr(mcast_ifaddr);
  112.         if (ifaddr.s_addr == (unsigned)-1)
  113.         {
  114.         hp = gethostbyname(mcast_ifaddr);
  115.         if (hp)
  116.         {
  117.             bcopy(hp->h_addr, (caddr_t)&ifaddr, hp->h_length);
  118.         }
  119.         else
  120.         {
  121.             fprintf(stderr, "Can't find IP address for '%s'\n",
  122.                 mcast_ifaddr);
  123.             close(fd);
  124.             return(-1);
  125.         }
  126.         }
  127.         if (setsockopt(fd, IPPROTO_IP, IP_MULTICAST_IF, &ifaddr, 
  128.                sizeof(ifaddr)) < 0)
  129.         {
  130.         perror("Can't send mcasts on the specified interface");
  131.         close(fd);
  132.         return(-1);
  133.         }
  134.         mreq.imr_interface = ifaddr;
  135.     }
  136.     else
  137.     {
  138.         mreq.imr_interface.s_addr = INADDR_ANY;
  139.     }
  140.  
  141.     mreq.imr_multiaddr.s_addr = addr->sin_addr.s_addr = 
  142.         inet_addr(DOG_MCAST_ADDR);
  143.     if (setsockopt(fd, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq, 
  144.                sizeof(mreq)) < 0)
  145.     {
  146.         perror("Can't add mcast address"); 
  147.         fprintf(stderr,
  148.             "Can't use multicast mode, reverting to broadcast mode.\n");
  149.         multicast = 0;    /* fall through */
  150.     }
  151.     } 
  152.  
  153.     if (!multicast)
  154.     {
  155.     addr->sin_addr.s_addr = INADDR_BROADCAST;
  156.     if (setsockopt(fd, SOL_SOCKET, SO_BROADCAST, &on, sizeof (on)) < 0)
  157.     {
  158.         perror("setsockopt");
  159.         close(fd);
  160.         return(-1);
  161.     }
  162.     }
  163.  
  164.     if (ioctl(fd, FIONBIO, &on) < 0)    /* Turn on non-blocking I/O */
  165.     {
  166.     perror("ioctl");
  167.     close(fd);
  168.     return(-1);
  169.     }
  170.     
  171.     (void) gethostaddr(&hostaddr);
  172.  
  173.     return(fd);
  174. }
  175.  
  176.  
  177. /*
  178.  * Get host internet address
  179.  */
  180.  
  181. int
  182. gethostaddr(addr)
  183.     struct sockaddr_in *addr;
  184. {
  185.     char hostname[100];
  186.     struct hostent *hp;
  187.  
  188.     if (gethostname(hostname, sizeof(hostname)) < 0)
  189.     return(-1);
  190.     hp = gethostbyname(hostname);
  191.     if (!hp)
  192.     return(-1);
  193.     addr->sin_family = AF_INET;
  194.     addr->sin_port = 0;
  195.     bcopy(hp->h_addr, &addr->sin_addr, sizeof(addr->sin_addr));
  196.     return(0);
  197. }
  198.  
  199.  
  200. /*
  201.  * sendbroadcast
  202.  */
  203.     
  204. int
  205. sendbroadcast(broadcastsocket, message, messagelength, addr)
  206.     int            broadcastsocket;
  207.     char *        message;
  208.     int            messagelength;
  209.     struct sockaddr_in *addr;
  210. {
  211.     return(sendto(broadcastsocket, message, messagelength, 0, addr,
  212.           sizeof(*addr)));
  213. }
  214.  
  215.  
  216. /*
  217.  *  recvbroadcast
  218.  */
  219. int
  220. recvbroadcast(broadcastsocket, message, messagelength, ignoreown)
  221.     int broadcastsocket;
  222.     char *message;
  223.     int messagelength;
  224.     int ignoreown;
  225. {
  226.     struct sockaddr_in fromaddr;
  227.     int fromaddrlength = sizeof(fromaddr);
  228.     int charcount;
  229.     
  230.     do
  231.     {
  232.     charcount=recvfrom(broadcastsocket, message, messagelength, 0,
  233.                 &fromaddr, &fromaddrlength);
  234.     if (charcount < 0)
  235.     {
  236.         if (errno == EWOULDBLOCK)
  237.         return(0);
  238.         else
  239.         {
  240.         perror("recvbroadcast");
  241.         exit(-1);
  242.         }
  243.     }
  244.  
  245.     if (charcount == 0)
  246.         break;
  247.  
  248.     } while (ignoreown &&
  249.          (fromaddr.sin_addr.s_addr == hostaddr.sin_addr.s_addr));
  250.  
  251.     return(charcount);
  252. }
  253.